// Created by Windward Studios - no copyright is claimed. This code can be used in
// any manner by anyone for any reason. There is no copyright of any kind on it. You may
// use it in commercial products. You may change it without sharing those changes.
// We ask that you keep the "created by Windward Studios" in a comment at the top.

using System;

namespace net.windward.utils.ado
{
	/// <summary>
	/// Credentials to connect to a database.
	/// </summary>
	public sealed class WrCredentials : IEquatable<WrCredentials>
	{
		private readonly string domain;
		private readonly string username;
		private readonly string password;
		private readonly bool useWindowsIdentity;

		/// <summary>
		/// Create credentials using a username and password.
		/// </summary>
		/// <param name="username">The username or the domain\username.</param>
		/// <param name="password">The password.</param>
		public WrCredentials(string username, string password)
		{

			if (username == null)
				this.username = username;
			else
			{
				int pos = username.IndexOf('\\');
				if (pos == -1)
					this.username = username;
				else
				{
					domain = username.Substring(0, pos);
					this.username = username.Substring(pos + 1);
				}
			}
			this.password = password;
			useWindowsIdentity = false;
		}

		/// <summary>
		/// Create credentials using domain, username, and password
		/// </summary>
		/// <param name="domain">The domain of the user.</param>
		/// <param name="username">The username of the user.</param>
		/// <param name="password">The password.</param>
		public WrCredentials(string domain, string username, string password)
		{
			this.domain = domain;
			this.username = username;
			this.password = password;
		}

		/// <summary>
		/// Create credentials using the current user's WindowsIdentity.
		/// </summary>
		public WrCredentials()
		{
			useWindowsIdentity = true;
		}

		/// <summary>
		/// Create using a copy constructor.
		/// </summary>
		/// <param name="src">Create an object with these values.</param>
		public WrCredentials(WrCredentials src)
		{
			domain = src.domain;
			username = src.username;
			password = src.password;
			useWindowsIdentity = src.useWindowsIdentity;
		}

		/// <summary>
		/// The login domain. null if no domain.
		/// </summary>
		public string Domain
		{
			get { return domain; }
		}

		/// <summary>
		/// The login username.
		/// </summary>
		public string Username
		{
			get { return username; }
		}

		/// <summary>
		/// The domain\username of the user. If no domain it is username.
		/// </summary>
		public string FullName
		{
			get
			{
				if (string.IsNullOrEmpty(domain))
					return username;
				if (string.IsNullOrEmpty(username))
					return domain + '\\';
				return domain + '\\' + username;
			}
		}

		/// <summary>
		/// The login password.
		/// </summary>
		public string Password
		{
			get { return password; }
		}

		/// <summary>
		/// True if using WindowsIdentity, false if using username and password.
		/// </summary>
		public bool UseWindowsIdentity
		{
			get { return useWindowsIdentity; }
		}

		/// <summary>
		/// Determines whether the specified credentials is equal to the current.
		/// </summary>
		/// <param name="wrCredentials">The credentials to comapre with the current.</param>
		/// <returns>true if the specified credentials is equal to the current.</returns>
		public bool Equals(WrCredentials wrCredentials)
		{
			if (wrCredentials == null) return false;
			if (!Equals(domain, wrCredentials.domain)) return false;
			if (!Equals(username, wrCredentials.username)) return false;
			if (!Equals(password, wrCredentials.password)) return false;
			if (!Equals(useWindowsIdentity, wrCredentials.useWindowsIdentity)) return false;
			return true;
		}
		
		///<summary>
		///Determines whether the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>.
		///</summary>
		///<returns>
		///true if the specified <see cref="T:System.Object"></see> is equal to the current <see cref="T:System.Object"></see>; otherwise, false.
		///</returns>
		///<param name="obj">The <see cref="T:System.Object"></see> to compare with the current <see cref="T:System.Object"></see>. </param><filterpriority>2</filterpriority>
		public override bool Equals(object obj)
		{
			if (ReferenceEquals(this, obj)) return true;
			return Equals(obj as WrCredentials);
		}

		///<summary>
		///Serves as a hash function for a particular type. <see cref="M:System.Object.GetHashCode"></see> is suitable for use in hashing algorithms and data structures like a hash table.
		///</summary>
		///<returns>
		///A hash code for the current <see cref="T:System.Object"></see>.
		///</returns>
		///<filterpriority>2</filterpriority>
		public override int GetHashCode()
		{
			int result = username != null ? username.GetHashCode() : 0;
			result ^= (domain != null ? domain.GetHashCode() : 0);
			result ^= (password != null ? password.GetHashCode() : 0);
			result ^= useWindowsIdentity.GetHashCode();
			return result;
		}
	}
}
